
/* Includes ------------------------------------------------------------------*/
#include "Ospi_Norflash.h"

extern OSPI_HandleTypeDef 	hospi1;
#define hospi 				&hospi1



uint8_t OSPI_SendCmd(uint32_t cmd, uint32_t cmdMode, uint32_t cmdSize, 
					uint32_t addr, uint32_t addrMode, uint32_t addrSize, 
					uint32_t dataMode, uint32_t dataSize, uint32_t dummy)
{
    OSPI_RegularCmdTypeDef  sCommand = {0};

    /* Configure automatic polling mode to wait for memory ready ------ */  
    sCommand.OperationType      = HAL_OSPI_OPTYPE_COMMON_CFG;
    sCommand.FlashId            = HAL_OSPI_FLASH_ID_1;
    sCommand.Instruction        = cmd;
    sCommand.InstructionMode    = cmdMode;
    sCommand.InstructionSize    = cmdSize;
    sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
    sCommand.Address            = addr;
    sCommand.AddressMode        = addrMode;
    sCommand.AddressSize        = addrSize;
    sCommand.AddressDtrMode     = HAL_OSPI_ADDRESS_DTR_DISABLE;
    sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
    sCommand.DataMode           = dataMode;
    sCommand.DataDtrMode        = HAL_OSPI_DATA_DTR_DISABLE;
    sCommand.NbData             = dataSize;
    sCommand.DummyCycles        = dummy;
    sCommand.DQSMode            = HAL_OSPI_DQS_DISABLE;
    sCommand.SIOOMode           = HAL_OSPI_SIOO_INST_EVERY_CMD;	

    if (HAL_OSPI_Command(hospi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
    {
      return OSPI_ERROR;
    }
    return OSPI_OK;	
}

uint8_t OSPI_Receive(uint8_t* buf, uint32_t len)
{
    // hospi->Instance->DLR = len - 1;
    if (HAL_OSPI_Receive(hospi, buf, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
    {
      return OSPI_ERROR;
    }
    return OSPI_OK;
}

uint8_t OSPI_Transmit(uint8_t* buf, uint32_t len)
{
    // hospi->Instance->DLR = len - 1;
    if(HAL_OSPI_Transmit(hospi, buf, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
    {
      return OSPI_ERROR;
    }
    return OSPI_OK;
}

uint8_t OSPI_SetQE(void)
{
  uint8_t ret = OSPI_ERROR;
  uint8_t reg = 0x02;

    ret = OSPI_SendCmd(CMD_WRITE_ENABLE, HAL_OSPI_INSTRUCTION_1_LINE, HAL_OSPI_INSTRUCTION_8_BITS,
				0, HAL_OSPI_ADDRESS_NONE, HAL_OSPI_ADDRESS_24_BITS, 
				HAL_OSPI_DATA_NONE, 0, 0);
    if(ret != OSPI_OK)
    {
      printf("%s fail: %d\r\n", __func__, __LINE__);
      return OSPI_ERROR;
    }
    
    ret = OSPI_SendCmd(CMD_WRITE_STATUSREG_2, HAL_OSPI_INSTRUCTION_1_LINE, HAL_OSPI_INSTRUCTION_8_BITS,
				0, HAL_OSPI_ADDRESS_NONE, HAL_OSPI_ADDRESS_24_BITS,
				HAL_OSPI_DATA_1_LINE, 1, 0);
    if(ret != OSPI_OK)
    {
      printf("%s fail: %d\r\n", __func__, __LINE__);
      return OSPI_ERROR;
    }
    
    ret = OSPI_Transmit(&reg, 1);
    if(ret != OSPI_OK)
    {
      printf("%s fail: %d\r\n", __func__, __LINE__);
      return OSPI_ERROR;
    }
    
    OSPI_WaitIdle();
    
    return OSPI_OK;
}

uint32_t OSPI_ReadId(void)
{
    uint8_t pData[3];

    OSPI_SendCmd(CMD_READ_ID, HAL_OSPI_INSTRUCTION_1_LINE, HAL_OSPI_INSTRUCTION_8_BITS,
                  0, HAL_OSPI_ADDRESS_NONE, HAL_OSPI_ADDRESS_24_BITS,
                  HAL_OSPI_DATA_1_LINE, 3, 0);

    OSPI_Receive(pData, 3);

    return (pData[0] << 16) | (pData[1] << 8) | pData[2];
}

void OSPI_WaitIdle(void)
{
    uint8_t reg = 0;
    do{
        OSPI_SendCmd(CMD_READ_STATUSREG, HAL_OSPI_INSTRUCTION_1_LINE, HAL_OSPI_INSTRUCTION_8_BITS,
                                0, HAL_OSPI_ADDRESS_NONE, HAL_OSPI_ADDRESS_24_BITS,
                                HAL_OSPI_DATA_1_LINE, 1, 0);
        OSPI_Receive(&reg, 1);
    }while( (reg & 0x01) == 0x01 );
}

uint8_t OSPI_EraseSector(uint32_t Address)
{
    OSPI_SendCmd(CMD_WRITE_ENABLE, HAL_OSPI_INSTRUCTION_1_LINE, HAL_OSPI_INSTRUCTION_8_BITS,
				0, HAL_OSPI_ADDRESS_NONE, HAL_OSPI_ADDRESS_24_BITS, 
				HAL_OSPI_DATA_NONE, 0, 0);
				
    OSPI_SendCmd(CMD_SECTOR_ERASE, HAL_OSPI_INSTRUCTION_1_LINE, HAL_OSPI_INSTRUCTION_8_BITS, 
				Address, HAL_OSPI_ADDRESS_1_LINE, HAL_OSPI_ADDRESS_24_BITS, 
				HAL_OSPI_DATA_NONE, 0, 0);
				
    OSPI_WaitIdle();
    
    return OSPI_OK;
}

void OSPI_Read(uint32_t Address, uint32_t Size, uint8_t * Buffer)
{
    OSPI_SendCmd(CMD_FAST_READDATA, HAL_OSPI_INSTRUCTION_1_LINE, HAL_OSPI_INSTRUCTION_8_BITS, 
                    Address, HAL_OSPI_ADDRESS_1_LINE, HAL_OSPI_ADDRESS_24_BITS, 
                    HAL_OSPI_DATA_4_LINES, Size, 8);

    OSPI_Receive(Buffer, Size);
}

uint8_t OSPI_Write_Page(uint32_t Address, uint32_t Size, uint8_t * Buffer)
{
    OSPI_SendCmd(CMD_WRITE_ENABLE, HAL_OSPI_INSTRUCTION_1_LINE, HAL_OSPI_INSTRUCTION_8_BITS,
				0, HAL_OSPI_ADDRESS_NONE, HAL_OSPI_ADDRESS_24_BITS, 
				HAL_OSPI_DATA_NONE, 0, 0);
				
    OSPI_SendCmd(CMD_PAGE_PROGRAM, HAL_OSPI_INSTRUCTION_1_LINE, HAL_OSPI_INSTRUCTION_8_BITS, 
            Address, HAL_OSPI_ADDRESS_1_LINE, HAL_OSPI_ADDRESS_24_BITS,
            HAL_OSPI_DATA_4_LINES, Size, 0);		
                            
    OSPI_Transmit(Buffer, Size);
    
    OSPI_WaitIdle();
    
    return OSPI_OK;
}

uint8_t OSPI_MemoryMapped(void)
{
    OSPI_MemoryMappedTypeDef sMMapCfg = {0};
    OSPI_RegularCmdTypeDef  sCommand = {0};
	
/* Send the write command */
    sCommand.OperationType 	 		= HAL_OSPI_OPTYPE_WRITE_CFG;
    sCommand.FlashId			 	= HAL_OSPI_FLASH_ID_1;
    sCommand.InstructionMode	 	= HAL_OSPI_INSTRUCTION_1_LINE;
    sCommand.InstructionDtrMode 	= HAL_OSPI_INSTRUCTION_DTR_DISABLE;
    sCommand.InstructionSize	 	= HAL_OSPI_INSTRUCTION_8_BITS;
    sCommand.Instruction		 	= CMD_PAGE_PROGRAM ;
    sCommand.AddressMode		 	= HAL_OSPI_ADDRESS_1_LINE;
    sCommand.AddressDtrMode	 		= HAL_OSPI_ADDRESS_DTR_DISABLE;
    sCommand.AddressSize		 	= HAL_OSPI_ADDRESS_24_BITS;
    sCommand.AlternateBytesMode 	= HAL_OSPI_ALTERNATE_BYTES_NONE;
    sCommand.DataMode			 	= HAL_OSPI_DATA_4_LINES;
    sCommand.DataDtrMode		 	= HAL_OSPI_DATA_DTR_DISABLE;
    sCommand.DummyCycles		 	= 0U;
    sCommand.DQSMode			 	= HAL_OSPI_DQS_ENABLE;
    sCommand.SIOOMode			 	= HAL_OSPI_SIOO_INST_EVERY_CMD;

    if (HAL_OSPI_Command(hospi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
    {
      printf("%s fail: %d\r\n", __func__, __LINE__);
      return OSPI_ERROR;
    }
/* Initialize the read command */
     sCommand.OperationType   	  = HAL_OSPI_OPTYPE_READ_CFG;
     sCommand.FlashId			  = HAL_OSPI_FLASH_ID_1;
     sCommand.InstructionMode	  = HAL_OSPI_INSTRUCTION_1_LINE;
     sCommand.InstructionDtrMode  = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
     sCommand.InstructionSize	  = HAL_OSPI_INSTRUCTION_8_BITS;
     sCommand.Instruction		  = CMD_FAST_READDATA_4IO ;
     sCommand.AddressMode		  = HAL_OSPI_ADDRESS_4_LINES;
     sCommand.AddressDtrMode	  = HAL_OSPI_ADDRESS_DTR_DISABLE;
     sCommand.AddressSize		  = HAL_OSPI_ADDRESS_24_BITS;
//   
     sCommand.AlternateBytesMode  = HAL_OSPI_ALTERNATE_BYTES_4_LINES;
     sCommand.AlternateBytes      = 0xFF;
     sCommand.AlternateBytesSize  = 1;
     sCommand.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE;
//             
     sCommand.DataMode 		  	  = HAL_OSPI_DATA_4_LINES;
     sCommand.DataDtrMode		  = HAL_OSPI_DATA_DTR_DISABLE;
     sCommand.DummyCycles		  = 4;
     sCommand.DQSMode	          = HAL_OSPI_DQS_DISABLE;
     sCommand.SIOOMode 		  	  = HAL_OSPI_SIOO_INST_EVERY_CMD;

    if (HAL_OSPI_Command(hospi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
    {
      printf("%s fail: %d\r\n", __func__, __LINE__);
      return OSPI_ERROR;
    }

    /* Configure the memory mapped mode */
    sMMapCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_DISABLE;

    if (HAL_OSPI_MemoryMapped(hospi, &sMMapCfg) != HAL_OK)
    {
    	printf("%s fail: %d\r\n", __func__, __LINE__);
      return OSPI_ERROR;
    }
    
    return OSPI_OK;
}

uint8_t OSPI_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size)
{
  uint8_t ret = OSPI_ERROR;
  uint32_t end_addr, current_size, current_addr;
  
  printf("OSPI_Wr size = 0x%x\r\n", Size);

  WriteAddr = WriteAddr & 0x0FFFFFFF;
  /* Calculation of the size between the write address and the end of the page */
  current_size = QSPI_PAGE_SIZE - (WriteAddr % QSPI_PAGE_SIZE);

  /* Check if the size of the data is less than the remaining place in the page */
  if (current_size > Size)
  {
    current_size = Size;
  }
  /* Initialize the adress variables */
  current_addr = WriteAddr;
  end_addr = WriteAddr + Size;

  /* Perform the write page by page */
  do
  {
    ret = OSPI_Write_Page(current_addr, current_size, pData);
    if(ret != OSPI_OK)
    {
    	printf("%s fail: 0x%x, 0x%x\r\n", __func__, current_addr, current_size);
    	return OSPI_ERROR;
    }
    /* Update the address and size variables for next page programming */
    current_addr += current_size;
    pData += current_size;
    current_size = ((current_addr + QSPI_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : QSPI_PAGE_SIZE;
  } while (current_addr < end_addr);
  
  printf("%s ok\r\n", __func__);
  return OSPI_OK;
}

uint8_t OSPI_AutoPollingMemReady(uint32_t Timeout)
{
    OSPI_RegularCmdTypeDef  sCommand = {0};
    OSPI_AutoPollingTypeDef sConfig = {0};

    sCommand.OperationType      = HAL_OSPI_OPTYPE_COMMON_CFG;
    sCommand.FlashId            = HAL_OSPI_FLASH_ID_1;
    sCommand.Instruction        = CMD_READ_STATUSREG;
    sCommand.InstructionMode    = HAL_OSPI_INSTRUCTION_1_LINE;
    sCommand.InstructionSize    = HAL_OSPI_INSTRUCTION_8_BITS;
    sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
    sCommand.Address            = HAL_OSPI_ADDRESS_NONE;
    sCommand.AddressMode        = HAL_OSPI_ADDRESS_24_BITS;
    sCommand.AddressSize        = 0;
    sCommand.AddressDtrMode     = HAL_OSPI_ADDRESS_DTR_DISABLE;
    sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
    sCommand.DataMode           = HAL_OSPI_DATA_1_LINE;
    sCommand.DataDtrMode        = HAL_OSPI_DATA_DTR_DISABLE;
    sCommand.NbData             = 1;
    sCommand.DummyCycles        = 0;
    sCommand.DQSMode            = HAL_OSPI_DQS_DISABLE;
    sCommand.SIOOMode           = HAL_OSPI_SIOO_INST_EVERY_CMD;	    

    sConfig.Match           = 0;
    sConfig.Mask            = 0x01;
    sConfig.MatchMode       = HAL_OSPI_MATCH_MODE_AND;
    sConfig.Interval        = 0x10;
    sConfig.AutomaticStop   = HAL_OSPI_AUTOMATIC_STOP_ENABLE;

    if (HAL_OSPI_AutoPolling(hospi, &sConfig, Timeout) != HAL_OK)
    {
        printf("%s fail: %d\r\n", __func__, __LINE__);
        return OSPI_ERROR;
    }

    return OSPI_OK;
}


/* USER CODE END 4 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
